<?php

namespace App\Http\Requests\Reservation;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;

class ScheduleStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     * @return array
     */
    public function rules()
    {
        return [
            'doctor_id'           => 'required|integer|min:1',
            'time'                => 'required|date',
            'room'                => 'required|integer|min:1',
            'workload'            => 'required|array|min:1|max:8',
            'workload.1'          => 'array|max:4',
            'workload.0'          => 'array|max:4',
            'workload.1.*.start'  => 'required_with:workload.1.*|integer|min:8|max:11',
            'workload.1.*.end'    => 'required_with:workload.1.*|integer|min:9|max:12|greater_than:workload.1.*.start',
            'workload.1.*.number' => 'required_with:workload.1.*|integer|min:1|max:999',
            'workload.0.*.start'  => 'required_with:workload.0.*|integer|min:13|max:16',
            'workload.0.*.end'    => 'required_with:workload.0.*|integer|min:14|max:17|greater_than:workload.0.*.start',
            'workload.0.*.number' => 'required_with:workload.0.*|integer|min:1|max:999',
        ];
    }

    public function messages()
    {
        return [
            'doctor_id.required' => '医生ID 字段不能为空。',
            'doctor_id.integer'  => '医生ID 必须是一个数字。',
            'doctor_id.min'      => '医生ID 必须大于等于 :min。',
            'time.required'      => '时间 不能为空。',
            'time.integer'       => '时间字段 必须是一个有效的日期。',
            'workload.required'  => '预约时间设置 不能为空。',
        ];
    }

    public function withValidator(Validator $validator)
    {
        $validator->after(function (Validator $validator) {
            if ($validator->messages()->isEmpty()) {
                //  预约时间不能有时间上的交叉 如：8点到10点，9点到11点 交叉时间为9点到10点
                $workload = $this->input('workload');
                if (isset($workload[1])) {
                    $am = collect($workload[1])->sortBy('start')->map(function ($work) {
                        return [$work['start'], $work['end']];
                    });
                    if (($am->count() > 1) && $this->is_cross($am->flatten(1)->toArray())) {
                        $validator->messages()->add('workload.1', '预约时间段不能有重叠。');
                    }
                }

                if (isset($workload[0])) {
                    $pm = collect($workload[0])->sortBy('start')->map(function ($work) {
                        return [$work['start'], $work['end']];
                    });

                    if (($pm->count() > 1) && $this->is_cross($pm->flatten(1)->toArray())) {
                        $validator->messages()->add('workload.0', '预约时间段不能有重叠。');
                    }
                }
            }
        });
    }

    /**
     * 经过排序后如果2个数组值相等，代表没有交叉的时间
     * @param $sections
     * @return bool
     */
    public function is_cross(array $sections)
    {
        $sort = $sections;

        sort($sort);

        return $sort != $sections;
    }
}
